package com.rr.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;
import redis.clients.jedis.JedisPoolConfig;

import javax.annotation.Resource;
import java.time.Duration;

/**
 * @author liyong$@skieer.com
 * @date 2022-11-16 2:49 下午
 */
@Configuration
public class RedisTemplateConfiguration {

    private final Logger log = LoggerFactory.getLogger(RedisTemplateConfiguration.class);

    /**
     * redis的连接配置
     */
    @Resource
    private MyRedisProperties.RedisDataSource redisPrimary;

    @Resource
    private MyRedisProperties.RedisDataSource redisSecond;

    private static final int DATABASE = 10;
    private static final int MAX_IDLE = 100;
    private static final int MIN_IDLE = 100;
    private static final int MAX_TOTAL = 1000;
    private static final int MAX_WAIT = 120000;

    /**
     * 主题服务默认使用的redisTemplate
     * @param jedisConnectionFactory redis连接工厂
     * @return 默认的redisTemplate，使用db0
     */
    @Bean
    @Primary
    public StringRedisTemplate stringRedisTemplate(@Qualifier("redisConnectionFactory") RedisConnectionFactory jedisConnectionFactory){
        return new StringRedisTemplate(jedisConnectionFactory);
    }

    /**
     * 主题值缓存专用的redisTemplate
     * @param redisConnectionFactorySecond redis连接工厂
     * @return 额外的redisTemplate，使用db10
     */
    @Bean
    public StringRedisTemplate stringRedisTemplateSecond(@Qualifier("redisConnectionFactorySecond") RedisConnectionFactory redisConnectionFactorySecond){
        return new StringRedisTemplate(redisConnectionFactorySecond);
    }

    /**
     * 连接池配置信息
     */
    @Bean
    public JedisPoolConfig jedisPoolConfig() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        //最大连接数
        jedisPoolConfig.setMaxTotal(MAX_TOTAL);
        //最小空闲连接数
        jedisPoolConfig.setMinIdle(MIN_IDLE);
        //最大空闲连接数
        jedisPoolConfig.setMaxIdle(MAX_IDLE);
        //当池内没有可用连接时，最大等待时间
        jedisPoolConfig.setMaxWaitMillis(MAX_WAIT);
        jedisPoolConfig.setTestOnBorrow(true);
        //其他属性可以自行添加
        return jedisPoolConfig;
    }

    private JedisConnectionFactory createRedisConnectionFactory(JedisPoolConfig jedisPoolConfig, MyRedisProperties.RedisDataSource dataSource, int database) {
        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
        //设置redis服务器的host或者ip地址
        redisStandaloneConfiguration.setHostName(dataSource.getHost());
        redisStandaloneConfiguration.setPort(Integer.parseInt(dataSource.getPort()));
        redisStandaloneConfiguration.setDatabase(database);
        if (!StringUtils.isEmpty(dataSource.getPassword())) {
            final RedisPassword of = RedisPassword.of(dataSource.getPassword());
            redisStandaloneConfiguration.setPassword(of);
        }
        //获得默认的连接池构造
        //这里需要注意的是，edisConnectionFactoryJ对于Standalone模式的没有（RedisStandaloneConfiguration，JedisPoolConfig）的构造函数，对此
        //我们用JedisClientConfiguration接口的builder方法实例化一个构造器，还得类型转换
        JedisClientConfiguration.JedisPoolingClientConfigurationBuilder jpcf = (JedisClientConfiguration.JedisPoolingClientConfigurationBuilder) JedisClientConfiguration.builder();
        //修改我们的连接池配置
        jpcf.poolConfig(jedisPoolConfig);
        final JedisClientConfiguration jedisClientConfiguration = jpcf.and().readTimeout(Duration.ofMillis(5000))
                .connectTimeout(Duration.ofMillis(5000))
                .build();
        //通过构造器来构造jedis客户端配置

        return new JedisConnectionFactory(redisStandaloneConfiguration, jedisClientConfiguration);
    }

    @Bean
    @Primary
    public RedisConnectionFactory redisConnectionFactory(JedisPoolConfig jedisPoolConfig) {
        log.info(">>>>>>>>>>>>>>>>>>>> init redisConnectionFactory dataConfig:{}", redisPrimary);
        return createRedisConnectionFactory(jedisPoolConfig, redisPrimary, 0);
    }

    @Bean
    public RedisConnectionFactory redisConnectionFactorySecond(JedisPoolConfig jedisPoolConfig) {
        log.info(">>>>>>>>>>>>>>>>>>>> init redisConnectionFactorySecond dataConfig:{}", redisSecond);
        return createRedisConnectionFactory(jedisPoolConfig, redisSecond, DATABASE);
    }

}
